
extends Node2D
var struct_message = preload("res://script/struct/struct_message.gd")
var struct_factory = preload("res://script/struct/struct_factory.gd")
var proto_message = preload("res://script/protobuf/message.gd")
var game_connect = preload("res://script/network/connection.gd")
var error_code = preload("res://script/common/error_code.gd")

var game_url = "ws://159.75.134.110:8002"
var login_url = "ws://159.75.134.110:8005"

var login_connecter = game_connect.new()
var game_connecter = game_connect.new()
var data_define_mgr = CDataDefineMgr.new()

# 效率不知道高不高，后面需要换成环形buff，整个过程不涉及到内存重分配，性能最佳
var send_buffer = StreamPeerBuffer.new()
var is_connected_server = false
var is_logining = false
var line_array: Array
var cur_line_data = {}

var _session_id = "0"
var _account_name = "123"
var _str_token = "test"
var _server_id = 0
var _common_version = 23743

var sock_list = []

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	struct_factory.initialize()
	login_connecter.add_listener("connected", Callable(self, "_on_login_connected"))
	login_connecter.on_message(struct_message.CS2C_SyncServerTime, self, "_on_sync_server_time")
	login_connecter.on_message(proto_message.L2C_QueryGameLine, self, "_on_recv_query_line")
	login_connecter.on_message(proto_message.L2C_CreatePlayer, self, "on_recv_create_player")
	login_connecter.on_message(proto_message.L2C_LoginGame, self, "on_recv_login_game")
	login_connecter.on_message(proto_message.L2C_LoginPlayer, self, "on_recv_login_player")

	print("begin connect login_url = ", login_url)
	login_connecter.connect_to_url(login_url)
	sock_list.append(login_connecter) 

	game_connecter.add_listener("connected", Callable(self, "_on_game_connected"))
	game_connecter.on_message(proto_message.S2C_LoginGameServer, self, "_on_login_game_server")
	game_connecter.on_message(proto_message.S2C_CreatePlayer, self, "_on_recv_create_player")
	game_connecter.on_message(proto_message.S2C_NotifyLoadScene, self, "_on_notify_load_scene")

func _on_login_connected(ctx):
	_send_query_line()

func _on_sync_server_time(msg):
	print("_on_sync_server_time msg = ", msg)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	for sock in sock_list:
		sock.process()


func _send_query_line():
	var msg = proto_message.C2L_QueryGameLine.new()
	login_connecter.send_data(msg)

func _on_recv_query_line(msg):
	print("_on_recv_query_line ", msg)
	line_array = msg.get_lineValue()
	if not line_array :
		print("error query line")
		return
	send_login_game(_session_id, _account_name)

func send_login_game(session_id, str_account_name):
	var msg = proto_message.C2L_LoginGame.new()
	msg.set_strAccountName(str_account_name)
	msg.set_strToken(_str_token)
	msg.set_nTime(0)
	msg.set_nServerId(0)
	msg.set_nCommonVersion(_common_version)
	login_connecter.send_data(msg)

func on_recv_login_game(msg):
	print("on_recv_login_game msg = ", msg)
	var ret_code = msg.get_nRetCode()
	if ret_code == error_code.USER_NOT_EXIST:
		create_user(_account_name, _session_id)
	elif ret_code != error_code.SUCCESS:
		print("unknow error ret_code = ", ret_code)
		return
	
	var player_list = msg.get_vecPlayer()
	if not player_list:
		create_player(_account_name)
		return
	
	login_player()


func create_user(str_account, sid):
	print("create_user str_account = ", str_account, ", sid = ", sid)
	var msg = proto_message.C2L_CreateUser.new()
	msg.set_strUserName(str_account)
	login_connecter.send_data(msg)

func on_recv_create_user(msg):
	print("on_recv_create_user msg = ", msg)
	if msg.get_nRetCode() != error_code.SUCCESS:
		return
	send_login_game(_account_name, _session_id)

func create_player(str_account_name):
	print("create_player str_account_name = ", str_account_name)
	var msg = proto_message.C2L_CreatePlayer.new()
	msg.set_strCharName(str_account_name)

	login_connecter.send_data(msg)

func on_recv_create_player(msg):
	print("on_recv_create_player msg = ", msg)
	login_player()
	
	
func login_player():
	if not line_array or line_array.size() == 0:
		print("line is empty")
		return
	# 随机一个服务器 进行用户登录
	var size = line_array.size()
	var rand_index = randi() % size
	var line_info = line_array[rand_index]
	var msg = proto_message.C2L_LoginPlayer.new()
	msg.set_strIP(line_info.get_strIP())
	msg.set_nPort(line_info.get_nPort())
	login_connecter.send_data(msg)
	
func on_recv_login_player(msg):
	print("on_recv_login_player msg = ", msg)
	cur_line_data = msg
	var game_server_ip = cur_line_data.get_strGameServerIP()
	var game_server_port = cur_line_data.get_nGameServerPort()
	game_url = "ws://%s:%d" % [game_server_ip, game_server_port]
	print("game_url = ", game_url)
	game_connecter.connect_to_url(game_url)
	sock_list.append(game_connecter)

func _on_game_connected(ctx):
	print("_on_game_connected", game_connecter._url)
	var main_player_id = cur_line_data.get_dPlayerID()
	var nToken = cur_line_data.get_nToken()
	send_login_server(main_player_id, nToken)

func send_login_server(player_id, token):
	var msg = proto_message.C2S_LoginGameServer.new()
	msg.set_dPlayerID(player_id)
	msg.set_nToken(token)
	msg.set_nIsPhone(1)
	msg.set_nLang(1)
	msg.set_strNation("cn")
	msg.set_strPlatform("an")
	game_connecter.send_data(msg)

func _on_login_game_server(msg):
	print("_on_login_game_server msg = ", msg)


func _on_recv_create_player(msg):
	var main_player_uuid = msg.get_UUID()
	print("_on_recv_create_player main_player_uuid = ",main_player_uuid)
	var bufferStream = CBufferStream.new(msg.get_PlayerData())
	var player_data = data_define_mgr.AllocPlayerDataDefine(main_player_uuid, null)
	player_data.UnPack(bufferStream, msg.get_datasize(), 0)
	

func _send_client_scene_loaded():
	var msg = proto_message.C2S_ClientSceneLoaded.new()
	game_connecter.send_data(msg)

func _on_notify_load_scene(data):
	_send_client_scene_loaded()
	
